package com.liming.common.util;

import cn.hutool.core.util.ObjectUtil;
import com.liming.common.enums.DateScopeEnum;
import com.liming.common.exception.BusinessException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;

/**
 * @author liming
 * @date 2025/2/25
 */
@Slf4j
public class TimeUtils {

    /**
     * 根据日期范围枚举获取时间范围
     *
     * @param dateScopeEnum 日期范围枚举
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getByDateScopeEnum(DateScopeEnum dateScopeEnum) {
        if (ObjectUtil.isNull(dateScopeEnum)) {
            throw new BusinessException("日期范围枚举为null空值");
        }
        return switch (dateScopeEnum) {
            case LAST_YEAR -> getLastYearDateRange();
            case LAST_MONTH -> getLastMonthDateRange();
            case LAST_WEEK -> getLastWeekDateRange();
            case YESTERDAY -> getYesterdayDateRange();
            case TODAY -> getTodayDateRange();
            case THIS_WEEK -> getThisWeekDateRange();
            case THIS_MONTH -> getThisMonthDateRange();
            case THIS_YEAR -> getThisYearDateRange();
            default -> throw new RuntimeException("暂不支持该日期范围");
        };
    }

    /**
     * 获取 去年的开始时间 - 去年结束时间 - 总天数
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getLastYearDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfYear = now.minusYears(1).withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfYear = now.minusYears(1).with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfYear);
        times.setEnd(endOfYear);
        times.setDays(getDaysBetween(startOfYear, endOfYear));
        return times;
    }


    /**
     * 获取 上月的开始时间 - 上个月结束时间 - 总天数
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getLastMonthDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfMonth = now.minusMonths(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfMonth = now.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfMonth);
        times.setEnd(endOfMonth);
        times.setDays(getDaysBetween(startOfMonth, endOfMonth));
        return times;
    }

    /**
     * 获取 上周的开始时间 - 上周结束时间 - 总天数
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getLastWeekDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfWeek = now.minusWeeks(1).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfWeek = now.minusWeeks(1).with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).withHour(23).withMinute(59).withSecond(59);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfWeek);
        times.setEnd(endOfWeek);
        times.setDays(getDaysBetween(startOfWeek, endOfWeek));
        return times;
    }

    /**
     * 获取 昨日的开始时间 - 昨日结束时间 - 总天数
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getYesterdayDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfYesterday = now.minusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfYesterday = now.minusDays(1).withHour(23).withMinute(59).withSecond(59);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfYesterday);
        times.setEnd(endOfYesterday);
        times.setDays(getDaysBetween(startOfYesterday, endOfYesterday));
        return times;
    }

    /**
     * 获取 本日的开始时间 - 目前时间 - 几天
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getTodayDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(now.withHour(0).withMinute(0).withSecond(0).withNano(0));
        times.setEnd(now);
        times.setDays(1L);
        return times;
    }

    /**
     * 获取 本周的开始时间 - 目前时间 - 几天
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getThisWeekDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfWeek);
        times.setEnd(now);
        times.setDays(getDaysBetween(startOfWeek, now));
        return times;
    }

    /**
     * 获取 本月的开始时间 - 目前时间 - 几天
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getThisMonthDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfMonth = now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfMonth);
        times.setEnd(now);
        times.setDays(getDaysBetween(startOfMonth, now));
        return times;
    }

    /**
     * 获取 今年的开始时间 - 目前时间 - 几天
     *
     * @return LocalDateTimeRange
     */
    public static LocalDateTimeRange getThisYearDateRange() {
        LocalDateTime now = LocalDateTime.now().withNano(0);
        LocalDateTime startOfYear = now.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTimeRange times = new LocalDateTimeRange();
        times.setStart(startOfYear);
        times.setEnd(now);
        times.setDays(getDaysBetween(startOfYear, now));
        return times;
    }

    public static String localDateNowString() {
        return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
    }

    public static String localDateTimeNowString() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
    }

    public static void main(String[] args) {
        LocalDateTimeRange date = getYesterdayDateRange();
        log.info("开始时间:{}", date.getStart());
        log.info("结束时间:{}", date.getEnd());
        log.info("天数:{}", date.getDays());
    }

    /**
     * 获取两个时间间隔的天数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 天数
     */
    public static Long getDaysBetween(LocalDateTime start, LocalDateTime end) {
        return ChronoUnit.DAYS.between(start, end) + 1;
    }

    @Data
    public static class LocalDateTimeRange {

        /**
         * 第一天
         */
        private LocalDateTime start;

        /**
         * 最后时间（若是周期没结束，则是当天）
         */
        private LocalDateTime end;

        /**
         * 几天
         */
        private Long days;
    }
}
